package com.yfbao.encryptor;

import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class LambdaUtils {

    private static final Map<Class<?>, SerializedLambda> LAMBDA_CACHE = new ConcurrentHashMap<>();

    /**
     * 获取Lambda表达式对应的字段名
     */
    public static <T> String getFieldName(SFunction<T, ?> lambda) {
        SerializedLambda serializedLambda = getSerializedLambda(lambda);
        String methodName = serializedLambda.getImplMethodName();

        if (methodName.startsWith("get")) {
            return methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
        } else if (methodName.startsWith("is")) {
            return methodName.substring(2, 3).toLowerCase() + methodName.substring(3);
        }
        return methodName;
    }

    /**
     * 获取Lambda表达式对应的字段
     */
    public static <T> Field getField(Class<T> entityClass, String fieldName) {
        Class<?> clazz = entityClass;
        while (clazz != null && clazz != Object.class) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field;
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass();
            }
        }
        return null;
    }

    /**
     * 获取序列化的Lambda信息
     */
    private static SerializedLambda getSerializedLambda(Object lambda) {
        return LAMBDA_CACHE.computeIfAbsent(lambda.getClass(), key -> {
            try {
                Method writeReplace = lambda.getClass().getDeclaredMethod("writeReplace");
                writeReplace.setAccessible(true);
                return (SerializedLambda) writeReplace.invoke(lambda);
            } catch (Exception e) {
                throw new RuntimeException("获取Lambda信息失败", e);
            }
        });
    }
}
